import socket
import time
import random
import string
from datetime import datetime,timedelta

def main(server_ip,server_port,total_packets):
    # 1.创建UDP套接字
    client_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

    # 2.模拟TCP连接建立
    client_socket.sendto('SYN'.encode(),(server_ip,server_port))
    message, server_address = client_socket.recvfrom(2048)
    if message.decode() == 'SYN-ACK':
        client_socket.sendto('ACK'.encode(), server_address)
        print("成功建立连接")
    else:
        print("连接建立失败, socket close")
        client_socket.close()
        return

    # 3.初始化
    lost_packets = 0#丢失报文数
    received_packets = 0#接受报文数
    ver = 2
    RTTs = []
    server_start_time=None#server第一次response系统时
    server_end_time=None#server最后一次response系统时

    # 开始传送数据报
    for i in range(total_packets):
        seq_no=i+1
        if seq_no<10:
            seq_no=f"0{seq_no}"
        word = ''.join(random.choices(string.ascii_letters, k=200))  # 随意生成200Byte的占位
        flag = 0#设置重传次数限制，只允许重传一次
        message=f"{seq_no}{ver}{word}"

        while True:
        # 发送:
            start_time = time.time()
            client_socket.sendto(message.encode(), (server_ip, server_port))
            client_socket.settimeout(0.1)

            try:
            # 接收服务器响应
                response, server_address = client_socket.recvfrom(2048)

                server_time=response[3:]#整体相应时间
                if server_start_time==None:
                    server_start_time=server_time
                else:
                    server_end_time=server_time

                end_time = time.time()
                received_packets += 1
                RTT = (end_time - start_time) * 1000
                RTTs.append(RTT)
                print(f"sequence no: {i+1}, server ip&port: {server_ip}:{server_port}, RTT: {RTT}ms")
                # received_packets+=1
                break
            except socket.timeout:  #处理超时
                flag += 1  #重传一次
                lost_packets += 1
                if flag<2:
                    continue
                else:
                    print(f"sequence no: {i+1}, request time out")
                    break

    # 模拟TCP-断开连接：
    client_socket.sendto('FIN1'.encode(), server_address)
    response, server_address = client_socket.recvfrom(2048)
    if response.decode() == 'server ACK':
        response, server_address = client_socket.recvfrom(2048)
        if response.decode() == 'FIN2':
            client_socket.sendto('client ACK'.encode(), server_address)
            client_socket.close()
            print("成功断开连接！")
        else:
            print("断开连接失败：未接收到server FIN")
    else:
        print("断开连接失败：未接收到client FIN")

    # 计算汇总信息
    rate =(lost_packets / (lost_packets+received_packets)) * 100
    max_rtt = max(RTTs)
    min_rtt = min(RTTs)
    avg_rtt = sum(RTTs) / received_packets
    rtt_std_dev = (sum([(x - avg_rtt) ** 2 for x in RTTs]) / received_packets) ** 0.5
    time1=datetime.strptime(str(server_start_time.decode()), "%H-%M-%S").replace(day=1, month=1, year=1)
    time2=datetime.strptime(str(server_end_time.decode()), "%H-%M-%S").replace(day=1, month=1, year=1)
    server_tot_time=int((time2-time1).total_seconds()*1000)

    print(f"共接收到{received_packets}个udp包")
    print(f"丢包率为: {rate:.2f}%")
    print(f"最大RTT为: {max_rtt}ms")
    print(f"最小RTT为: {min_rtt}ms")
    print(f"平均RTT为: {avg_rtt}ms")
    print(f"RTT的标准差为: {rtt_std_dev}ms")
    print(f"server整体相应时间为：{server_tot_time}ms")

if __name__ == "__main__":
    # 获取服务器IP和端口：
    server_ip = input("输入server IP：")#使用回环地址 127.0.0.1
    server_port = int(input("输入server port："))#12345
    total_packets = 12  # 总传输报文个数
    main(server_ip,server_port,total_packets)